//实现函数bind

Function.prototype.bind2 = function(ctx) {
    let self = this
    let agrs1 = []   //执行bind的时候传入的其他参数
    for(let i = 1; i < arguments.length; i++) {
        agrs1.push(arguments[i])
    }
    let FNOP = function() {}
    let fBound = function() {
        let args2 = Array.from(arguments)   //arguments：调用的时候传入的参数
        let args = agrs1.concat(args2)
        //instanceof检测fBound的prototype是否出现在this的原型链上
        //fBound.prototype.__proto__ === FNOP.prototype
        //当fBound作为构造函数时，this指向创建出的实例（详见new的实现），this.__proto__ === fBound.prototype，所以this instanceof fBound为true，传入this实例进行处理，使ctx失效。
        //当fBound为普通函数时，this为globalThis，this instanceof fBound为false，传入原来绑定的ctx
        return self.apply(this instanceof FNOP ? this : ctx, args)
    }
    FNOP.prototype = self.prototype
    fBound.prototype = new FNOP()   //修改返回函数的prototype，使返回函数作为构造函数时，实例可以访问原型中的值
    return fBound
}

let obj = {
    value: 1
}
//大家都这么食用
// function bar(name, age) {
//     console.log(this.value)
//     console.log(name, age)
// }
// bar = bar.bind2(obj, 'sam')
// bar(18)

//另一种食用方法
function foo(name, age){
    this.count = 1
    console.log(name, age)
}
foo = foo.bind2(obj, 'sam')
let fooObj = new foo(18)    //当bind返回的函数作为构造函数，new的时候，bind指定的this会失效，但是传入的参数依然生效。(应只有count属性，不应有value属性)
console.log(fooObj)
